#include "stdafx.h"
#include "GArea.h"

GArea GArea::AreaControl;

GArea::GArea() 
{    
	AreaSize = 0;
}

GArea::~GArea()
{
}

int GArea::GetAreaSize()
{
	return AreaSize;
}

bool GArea::OnLoad(char* File)
{
	MapList.clear();

	FILE* FileHandle = fopen(File, "r");

	if(FileHandle == NULL)
		return false;

	char TilesetFile[255];

	fscanf(FileHandle, "%s\n", TilesetFile);

	if((Surf_Tileset = SDLSurface::OnLoad(TilesetFile)) == false)
	{
		fclose(FileHandle);
		return false;
	}

	fscanf(FileHandle, "%d\n", &AreaSize);

	for(int Y = 0; Y < AreaSize; Y++)
	{
		for(int X = 0; X < AreaSize; X++)
		{
			char MapFile[255];

			fscanf(FileHandle, "%s ", MapFile);

			GMap tempMap;
			if(tempMap.OnLoad(MapFile) == false)
			{
				fclose(FileHandle);
				return false;
			}

			tempMap.Surf_Tileset = Surf_Tileset;

			MapList.push_back(tempMap);
		}
		fscanf(FileHandle, "\n");
	}
	fclose(FileHandle);

	return true;
}

/*
For this method, camera position should be negative. Think about this, 
the screen itself never moves, but if we press down, the role seems go down, 
actually its the map goes up, which means its up edge is further from the screen up edge.
So, for something move down, the two edges leave further, and if we want to draw the map,
the parameters (position to draw) should be negative, 
such as: OnDraw(Surf_Display, Surf_Map, negative_X, negative_Y)
*/
void  GArea::OnRender(SDL_Surface* Surf_Display, int CameraX, int CameraY)
{
	int MapWidth  = MAP_WIDTH * TILE_SIZE;    
	int MapHeight = MAP_HEIGHT * TILE_SIZE; 

	int FirstID = -CameraX / MapWidth;
	FirstID = FirstID + ((-CameraY / MapHeight) * AreaSize);

	//For our size of a screen, 640x480, only a possible 4 maps can be visible at one time.
	//So what we have to do is calculate the first Map ID to grab.
	for(int i = 0; i < 4; i++)
	{
		int ID = FirstID + ((i / 2) * AreaSize) + (i % 2);

		if(ID < 0 || ID >= MapList.size()) 
			continue;

		int X = ((ID % AreaSize) * MapWidth) + CameraX;
		int Y = ((ID / AreaSize) * MapHeight) + CameraY;

		MapList[ID].OnRender(Surf_Display, X, Y);
	}
}

void GArea::OnCleanup() 
{  
	if(Surf_Tileset) 
	{      
		SDL_FreeSurface(Surf_Tileset); 
	}    

	MapList.clear();
}

GMap* GArea::GetMap(int X, int Y)
{
	int MapWidth  = MAP_WIDTH * TILE_SIZE;
	int MapHeight = MAP_HEIGHT * TILE_SIZE;

	int ID = X / MapWidth;
	ID += (Y / MapHeight) * AreaSize;

	if(ID < 0 || ID >= MapList.size())
		return NULL;

	return &MapList[ID];
}

GTile* GArea::GetTile(int X, int Y)
{
	int MapWidth  = MAP_WIDTH * TILE_SIZE;
	int MapHeight = MAP_HEIGHT * TILE_SIZE;

	GMap* Map = GetMap(X, Y);

	if(Map == NULL) return NULL;

	X = X % MapWidth;
	Y = Y % MapHeight;

	return Map->GetTile(X, Y);
}